﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
using System.Windows.Forms;
using TSNPro.Utils;

namespace TSNPro.Base
{
    public class BaseManager
    {
        protected JObject _obj;
        protected List<BaseItem> _allItems;
        protected BaseFactory _factory = new BaseFactory();
        public BaseManager()
        {
            _allItems = new List<BaseItem>();
        }

        public void InitConfigFromObj(JObject obj)
        {
            _obj = obj;
            InitImpl(obj);
        }

        protected virtual void InitImpl(JObject obj)
        {
            string managerName = ManagerName();
            foreach (var key in obj.GetAllKeys())
            {
                JObject value = (JObject)obj[key];
                if (_factory == null)
                {
                    throw new Exception($"{managerName} 未配置 工厂实例");
                }
                BaseItem baseItem = _factory.CreateInstance(value["Type"].ToString());
                baseItem.Name = key;
                baseItem.SetConfig(value);
                baseItem.SetOtherConfig(value["OtherConfig"].ToObject<JObject>());
                if (!baseItem.Init())
                {
                    Console.WriteLine($"{System.Reflection.MethodBase.GetCurrentMethod().Name} failed to initialize: {key}");
                }
                _allItems.Add(baseItem);
            }
            Console.WriteLine($"{managerName} {_allItems.Count} Item(s)");
        }

        public string GetIconPath(string name)
        {
            JObject objItem = (JObject)_obj[name];
            return objItem["IconPath"].ToString();
        }

        public string GetFriendlyName(string name)
        {
            JObject objItem = (JObject)_obj[name];
            return objItem["FriendlyName"].ToString();
        }

        public List<string> GetNames()
        {
            return _obj.Properties().Select(p => p.Name).ToList();
        }

        public List<string> GetRegisterTypes()
        {
            return _factory.GetRegisterTypes();
        }

        public Form GetConfigWidget(string name)
        {
            BaseItem item = GetItem<BaseItem>(name);
            return item.GetConfigWidget() as Form;
        }

        public void SetFactory(BaseFactory factory)
        {
            _factory = factory;
        }

        public string ManagerName()
        {
            return this.GetType().FullName;
        }

        public void InitMenu(ContextMenuStrip menu)
        {
            foreach (var name in GetNames())
            {
                var act = new ToolStripMenuItem();
                string friendlyName = GetFriendlyName(name);
                act.Text = friendlyName;
                string iconPath = GetIconPath(name);
                act.Image = new System.Drawing.Bitmap(iconPath);
                menu.Items.Add(act);
                act.Click += (sender, e) =>
                {
                    WidgetUtils.Execute(null,() =>
                    {
                        BaseItem item = GetItem<BaseItem>(name);
                        Form w = GetConfigWidget(name);
                        w.Text = friendlyName;

                        if (w is Form dialog)
                        {
                            dialog.ShowDialog();
                            dialog.Dispose();
                        }
                        else
                        {
                            w.FormClosed += (sender2, e2) => w.Dispose();
                            w.ShowDialog();
                        }
                    }, true);
                };
            }
        }

        public void WaitForEnd()
        {
            // Add your implementation here
        }

        public T GetItem<T>(string name) where T : BaseItem
        {
            return _allItems.FirstOrDefault(item => item.Name == name) as T;
        }

        public List<T> GetItems<T>() where T : BaseItem
        {
            return _allItems.Cast<T>().ToList();
        }

        public List<T> GetItems<T>(List<string> names) where T : BaseItem
        {
            List<T> ret = new List<T>();
            foreach (string name in names)
            {
                ret.Add(GetItem<T>(name));
            }
            return ret;
        }
    }
}
